package org.jradweb.tools.generator.maven;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.dbunit.DatabaseUnitException;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.operation.DatabaseOperation;
import org.jradweb.tools.generator.utils.PropertiesLoader;

/**
 * Goal which touches a timestamp file.
 * 
 * @goal initData
 * @phase process-test-resources
 */
public class InitDataMojo extends AbstractMojo {

	public static final String DATABASE_DRIVER_CLASS_NAME = "database.driverClassName";

	public static final String DATABASE_URL = "database.url";

	public static final String DATABASE_USER_NAME = "database.userName";

	public static final String DATABASE_PASSWORD = "database.password";

	public static final String DATABASE_SCHEMA_NAME = "database.schemaNames";

	public static final String DATABASE_DIALECT = "database.dialect";

	/**
	 * ${project.build.directory}
	 * 
	 * @parameter expression="${project.build.directory}"
	 */
	private File buildPath;
	/**
	 *  @parameter expression="${basedir}"
	 */
	private File baseDir;

	/**
	 * @parameter expression="${project.groupId}"
	 */
	private String groupId;

	/**
	 * @parameter expression="${project.artifactId}"
	 */
	private String artifactId;

	public void execute() throws MojoExecutionException, MojoFailureException {
		 
		//check if only clean
		boolean onlyClean=false;		
		String clean=System.getProperties().getProperty("onlyClean");
		if(clean!=null&&clean.equals("true"))
			onlyClean=true;
		getLog().info("onlyClean = "+onlyClean);
		
		PropertiesLoader loader=new PropertiesLoader(this.baseDir,this.artifactId);
		//load database connection parameters
		Properties props = null;
		try {
			props = loader.loadProjectProperties();
		} catch (FileNotFoundException e) {
			throw new MojoFailureException("load " + this.artifactId
					+ ".properties failed. message:" + e.getMessage());
		} catch (IOException e) {
			throw new MojoFailureException("load " + this.artifactId
					+ ".properties failed. message:" + e.getMessage());
		}

		IDatabaseConnection connection = null;
		try {
			Class driverClass = Class.forName(props
					.getProperty(DATABASE_DRIVER_CLASS_NAME));
			Connection jdbcConnection = DriverManager.getConnection(props
					.getProperty(DATABASE_URL), props
					.getProperty(DATABASE_USER_NAME), props
					.getProperty(DATABASE_PASSWORD));
			connection = new DatabaseConnection(jdbcConnection);
		} catch (ClassNotFoundException e) {
			throw new MojoFailureException(
					"get database connection failed. message:" + e.getMessage());
		} catch (SQLException e) {
			throw new MojoFailureException(
					"get database connection failed. message:" + e.getMessage());
		}

		List<IDataSet> dataSets = this.getDataSets();
		for (int i = dataSets.size() - 1; i >= 0; i--) {
			IDataSet dataSet = dataSets.get(i);
			try {
				DatabaseOperation.DELETE_ALL.execute(connection, dataSet);
				getLog()
						.info(
								"Dataset "
										+ i
										+ " DELETE_ALL operation executed successfully.");
			} catch (DatabaseUnitException e) {
				e.printStackTrace();
				throw new MojoFailureException(
						"operator DELETE_ALL failed for dataset \"" + dataSet
								+ "\" . " + e.getMessage());
			} catch (SQLException e) {
				e.printStackTrace();
				throw new MojoFailureException(
						"operator DELETE_ALL failed for dataset \"" + dataSet
								+ "\" . message:" + e.getMessage());
			}
		}
		
		if(!onlyClean){
		for (int i = 0; i < dataSets.size(); i++) {
			IDataSet dataSet = dataSets.get(i);
			try {
				DatabaseOperation.INSERT.execute(connection, dataSet);
				getLog().info(
						"Dataset " + i
								+ " INSERT operation executed successfully.");
			} catch (DatabaseUnitException e) {
				throw new MojoFailureException(
						"operator INSERT failed for dataset \"" + dataSet
								+ "\" . message:" + e.getMessage());
			} catch (SQLException e) {
				throw new MojoFailureException(
						"operator INSERT failed for dataset \"" + dataSet
								+ "\" . message:" + e.getMessage());
			}
		}}

	}

	private List<IDataSet> getDataSets() throws MojoExecutionException,
			MojoFailureException {
		List<IDataSet> dataSets = new ArrayList<IDataSet>();

		File dataSetPath = new File(this.baseDir.getAbsolutePath()
				+ "/src/test/resources/dataset");
		if (!dataSetPath.exists() || !dataSetPath.isDirectory()) {
			throw new MojoFailureException(
					"DataSet path not exists,please create it: "
							+ dataSetPath.getAbsolutePath());
		}
		File[] files = dataSetPath.listFiles();
		for (File file : files) {
			try {
				String fileName = file.getName();
				getLog().info("Load dataSet file " + file.getName() + "...");
				if (fileName.matches("[0-9]{1,5}_[a-z,A-Z]{1,100}\\.xml")) {
					IDataSet dataSet = new FlatXmlDataSet(file);
					dataSets.add(dataSet);
					getLog().info("DataSet loaded.");
				}
			} catch (DataSetException e) {
				String message = "Load dataset from file failed. file:"
						+ file.getAbsolutePath();
				getLog().error(message);
				throw new MojoFailureException(
						"load dataset from file failed, message:"
								+ e.getMessage());
			} catch (IOException e) {
				String message = "Load dataset from file failed. file:"
						+ file.getAbsolutePath();
				getLog().error(message);
				throw new MojoFailureException(
						"load dataset from file failed, message:"
								+ e.getMessage());
			}
		}

		return dataSets;
	}
	/*
	 * load properties from ${artifactId}.properties
	 */
	private Properties loadProperties() throws FileNotFoundException,
			IOException {
		String propFile = baseDir.getAbsolutePath() + "/src/main/resources/"
				+ artifactId + ".properties";
		java.util.Properties props = new Properties();
		props.load(new FileInputStream(new File(propFile)));

		this.getLog().info(
				"database.driverClassName="
						+ props.getProperty("database.driverClassName"));
		this.getLog().info("database.url=" + props.getProperty("database.url"));
		this.getLog().info(
				"database.userName=" + props.getProperty("database.userName"));
		this.getLog().info(
				"database.password=" + props.getProperty("database.password"));
		this.getLog().info(
				"database.schemaNames="
						+ props.getProperty("database.schemaNames"));
		this.getLog().info(
				"database.dialect=" + props.getProperty("database.dialect"));
		return props;

	}
	

	public static void main(String[] args) throws MojoExecutionException,
			MojoFailureException {

		InitDataMojo dm = new InitDataMojo();
		File buildPath = new File("./test/src");
		dm.buildPath = buildPath;
		dm.artifactId = "vms";
		dm.groupId = "com.infowarelab";

		try {
			dm.execute();
		} catch (MojoExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MojoFailureException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
